import { on, CESIUM_VIEWER_INITIALIZATION } from '../../utils/EventBus.js'
import * as Cesium from 'cesium'
import repositoryCoords from '../mock-data/repositoryCoords.json'
import { MixedLayer } from '../../utils/MixedLayer'
import { SingleDebouncedCesiumMouseMove } from '../../components/cesium/screen-event/DebouncedCesiumMouseMove.js'
import { DomEntity } from '../../utils/DomEntity.js'
import './personnel.scss'

const cartesianArray = repositoryCoords.map((item) =>
    Cesium.Cartesian3.fromRadians(item.longitude, item.latitude, item.height)
)
export const rectangle = Cesium.Rectangle.fromCartesianArray(cartesianArray)

export function getRandomLonLatInRectangle(rectangle) {
    const { west, east, north, south } = rectangle
    const longitude = Cesium.Math.randomBetween(west, east)
    const latitude = Cesium.Math.randomBetween(south, north)
    // return [Cesium.Math.toDegrees(longitude), Cesium.Math.toDegrees(latitude)]
    return [longitude, latitude]
}

on(CESIUM_VIEWER_INITIALIZATION, () => {
    const singleDebouncedCesiumMouseMove = new SingleDebouncedCesiumMouseMove(
        cesiumViewer,
        100
    )

    singleDebouncedCesiumMouseMove.addCallback((pickedObject) => {
        if (!Personnel.instance) return
        const { domEntities } = Personnel.instance.ml
        domEntities.forEach((element) => {
            element.rootDom.firstElementChild.classList.remove('show')
        })
        if (
            Cesium.defined(pickedObject) &&
            pickedObject.id instanceof Cesium.Entity
        ) {
            const domEntity = domEntities.find(
                (element) => element._id === pickedObject.id.id
            )
            if (domEntity) {
                domEntity.rootDom.firstElementChild.classList.add('show')
            }
        }
    })
})

export class Personnel {
    static instance = null
    constructor() {
        this.ml = new MixedLayer()
        this.bindEvent()
    }

    create(data) {
        cesiumViewer.scene
            .sampleHeightMostDetailed(
                data.map(({ lonLat }) =>
                    Cesium.Cartographic.fromRadians(lonLat[0], lonLat[1])
                )
            )
            .then((cartographicArray) => {
                cartographicArray.forEach((cartographic, index) => {
                    const { longitude, latitude, height } = cartographic
                    const position = Cesium.Cartesian3.fromRadians(
                        longitude,
                        latitude,
                        height + 1
                    )
                    data[index].coord = { longitude, latitude, height }

                    this.ml.dataSource.entities.add({
                        id: index,
                        position,
                        point: {
                            disableDepthTestDistance: Number.POSITIVE_INFINITY,
                            pixelSize: 10,
                            color: Cesium.Color.RED,
                            outlineColor: Cesium.Color.WHITE,
                            outlineWidth: 2,
                        },
                    })

                    this.ml.domEntities.push(
                        new DomEntity({
                            parentDom:
                                document.querySelector('#cesiumContainer'),
                            id: index,
                            position,
                            html: `
    <div class="personnel-name-wrapper">
        <div class="personnel-name">
            ${data[index].name}
        </div>
    </div>
              `,
                            pixelOffset: new Cesium.Cartesian2(0, -10),
                            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                        })
                    )
                })
            })

        return this
    }

    bindEvent() {
        const depthFit = () => {
            const pitchDegree = Cesium.Math.toDegrees(cesiumViewer.camera.pitch)
            if (pitchDegree > -15) {
                this.ml.dataSource.entities.values.forEach((entity) => {
                    entity.point.disableDepthTestDistance = 0
                })
            } else {
                this.ml.dataSource.entities.values.forEach((entity) => {
                    entity.point.disableDepthTestDistance =
                        Number.POSITIVE_INFINITY
                })
            }
        }

        const removeMoveEndCallbak =
            cesiumViewer.camera.moveEnd.addEventListener(depthFit)
        const removeChangedCallbak =
            cesiumViewer.camera.changed.addEventListener(depthFit)
        this.ml.destroyCallback.push(removeMoveEndCallbak, removeChangedCallbak)
    }
}
